package com.fumin.service;

import com.fumin.common.RequestHolder;
import com.fumin.dao.SysAclMapper;
import com.fumin.dao.SysAclModuleMapper;
import com.fumin.exception.ParamException;
import com.fumin.model.SysAclModule;
import com.fumin.param.AclModuleParam;
import com.fumin.util.BeanValidator;
import com.fumin.util.IpUtil;
import com.fumin.util.LevelUtil;
import com.google.common.base.Preconditions;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @Author xiayuxuanmin
 * @Date 2019/11/1
 * @Description
 */
@Service
public class SysAclModuleService {
    //默认@Autowired是按类型type自动注入
    //默认@Resource是按名字byName自动注入，也可以指定type注入
    @Resource
    private SysAclModuleMapper sysAclModuleMapper;
    @Resource
    private SysAclMapper sysAclMapper;
    @Resource
    private SysLogService sysLogService;

    /**
     * 新增权限模块
     * @param param
     */
    public void save(AclModuleParam param){
        BeanValidator.check(param);//检测参数是否合法
        if (checkExist(param.getParentId(), param.getName(), param.getId())) {
            throw new ParamException("同一层级下存在相同名称的权限模块!");
        }
        SysAclModule sysAclModule = SysAclModule.builder().name(param.getName()).parentId(param.getParentId())
                .seq(param.getSeq()).status(param.getStatus()).remark(param.getRemark()).build();
        sysAclModule.setLevel(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()));
        sysAclModule.setOperator(RequestHolder.getCurrentUser().getUsername());//TODO:
        sysAclModule.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));//TODO:
        sysAclModule.setOperateTime(new Date());
        sysAclModuleMapper.insertSelective(sysAclModule);//insert和insertSelective的区别:insertSelective只插入有值的属性...
        sysLogService.saveAclModuleLog(null,sysAclModule);
    }

    /**
     * 更新权限模块
     * @param param
     */
    public void update(AclModuleParam param){
        BeanValidator.check(param);//检测参数是否合法
        if (checkExist(param.getParentId(), param.getName(), param.getId())) {
            throw new ParamException("同一层级下存在相同名称的权限模块!");
        }
        SysAclModule before = sysAclModuleMapper.selectByPrimaryKey(param.getId());
        Preconditions.checkNotNull(before, "待更新的权限模块不存在！");
        SysAclModule after = SysAclModule.builder().id(param.getId()).name(param.getName()).parentId(param.getParentId())
                .seq(param.getSeq()).status(param.getStatus()).remark(param.getRemark()).build();
        after.setLevel(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()));
        after.setOperator(RequestHolder.getCurrentUser().getUsername());
        after.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
        after.setOperateTime(new Date());
        updateWithChild(before, after);
        sysLogService.saveAclModuleLog(before,after);
    }

    /**
     * 更新权限模块的所有下级子孙级部门的LEVEL
     * @param before 更新前的记录
     * @param after  更新后的记录
     */
    @Transactional //添加事务，在修改子孙级部门的时候，要么一起成功，要么一起失败
    public void updateWithChild(SysAclModule before, SysAclModule after){
        String newLevelPrefix = after.getLevel();
        String oldLevelPrefix = before.getLevel();
        if (!newLevelPrefix.equals(oldLevelPrefix)) {
            //如果更新了部门的LEVEL（LEVEL不同，那么需要更新子孙级部门的LEVEL）
            List<SysAclModule> deptList = sysAclModuleMapper.getChildAclModuleListByLevel(before.getLevel());
            if (CollectionUtils.isNotEmpty(deptList)) {
                for (SysAclModule aclModule : deptList) {
                    String level = aclModule.getLevel();
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        //如果子孙级部门的LEVEL以老的LEVEL开头（oldLevelPrefix）
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        aclModule.setLevel(level);
                    }
                }
                sysAclModuleMapper.batchUpdateLevel(deptList);
            }
        }
        sysAclModuleMapper.updateByPrimaryKey(after);
    }

    /**
     * 判断同一个权限模块下是否有重复的子模块
     * @param parentId
     * @param aclModuleName
     * @param aclModuleId
     * @return
     */
    private boolean checkExist(Integer parentId,String aclModuleName,Integer aclModuleId){
        return sysAclModuleMapper.countByNameAndParentId(parentId,aclModuleName,aclModuleId) > 0;
    }

    /**
     * 获取指定的模块的层级
     * @param aclModuleId
     * @return
     */
    public String getLevel(Integer aclModuleId) {
        SysAclModule sysAclModule = sysAclModuleMapper.selectByPrimaryKey(aclModuleId);
        if (sysAclModule == null) {
            return null;
        }
        return sysAclModule.getLevel();
    }

    public void delete(int aclModuleId){
        SysAclModule aclModule = sysAclModuleMapper.selectByPrimaryKey(aclModuleId);
        Preconditions.checkNotNull(aclModule,"待删除的权限模块不存在,无法删除!");
        if (sysAclModuleMapper.countByParentId(aclModuleId) > 0) {
            throw new ParamException("当前权限模块下面有子模块,无法删除!");
        }
        if (sysAclMapper.countByAclModule(aclModuleId) > 0) {
            throw new ParamException("当前权限模块下面有权限点,无法删除!");
        }
        sysAclModuleMapper.deleteByPrimaryKey(aclModule.getId());
    }
}
